/**
 * \file Principal.cpp
 * \brief Fichier pour les différents tests
 * \author Pierre-Marc Levasseur, Simon Rodier
 * \version 0.1
 * \date juillet 2014
 *
 */

#include <iostream>
#include <fstream>
#include "ReseauAerien.h"
#include <time.h>
#include <vector>
//vous pouvez inclure d'autres librairies si c'est n�cessaire
using namespace std;
using namespace TP3;

const string originePossible = "Quebec";
const string destinationPossible = "Bogota";
//const string originePossible2 = "tbd";
//const string destinationPossible2 = "tbd";


#include "ReseauAerien.h"

void preparerVilles(string& origine, string& destination)
{
	//entrez le nom de la ville d'origine
	cout<<"Entrez le nom de la ville d'origine : ";
	getline(cin, origine);
	//entrez le nom de la ville de destination
	cout<<"Entrez le nom de la ville destination : ";
	getline(cin, destination);
}

void afficherChemin(Chemin ch, clock_t temps)
{
	if(!ch.reussi)
	{
		cout<<"Impossible de trouver la trajectoire la plus courte entre les deux villes."<<endl;
		return;
	}
	cout<<"Nombre de vols à prendre : "<<ch.listeVilles.size()-1<<endl;
	cout<<"Trajet : "<<endl;
	for (size_t it = 0; it<ch.listeVilles.size() ; it++)
	{
		cout<<"\t"<<ch.listeVilles[it]<<endl;
	}
	cout<<"***"<<endl;
	cout<<"Durée du trajet : "<<ch.dureeTotale<<endl;
	cout<<"Coût du trajet : "<<ch.coutTotal<<endl;
	cout<<"Niveau de sécurité total : "<<ch.nsTotal<<endl;
	cout<<"Temps d'exécution : "<<(float)temps/CLOCKS_PER_SEC*1000<<" millisecondes"<<endl;
	return;
}

int main()
{
	ReseauAerien reseau;
	cout << "TP3 : Réseau Aérien\npar Pierre-Marc Levasseur et Simon Rodier" << endl;
	cout << "---------------------\n" << endl;
	ifstream fichier;
	bool fichierOuvertCorrectement=true;
	do
	{

		// ouverture du fichier .txt contenant le bottin
		cout << "Veuillez saisir le nom du fichier (avec extension) contenant le réseau aérien à utiliser : ";
		string nomFichier;
		getline(cin, nomFichier);
		fichier.open(nomFichier.c_str(), ios::in);
		if(!fichier.is_open())
			cout << "**Fichier invalide. Veuillez entrer un autre nom." << endl;
		//charger le reseau aerien
		try
		{
			reseau.chargerReseau(fichier);
		}
		catch (bad_alloc& ba)
		{
			cout<<"Il n'y a pas suffisamment de mémoire pour charger le fichier."<<endl;
			fichierOuvertCorrectement=false;
		}
		catch (logic_error& le)
		{
			cout<<"Le fichier n'est pas ouvert correctement."<<endl;
			fichierOuvertCorrectement=false;
		}
	}
	while(!fichier.is_open() || fichierOuvertCorrectement==false);




	//ensuite on entre dans la boucle du programme
	bool continueProgramme = true;
	while(continueProgramme)
	{
		//demander le choix (incluant une option pour quitter)
		cout<<"Veuillez choisir une des options suivantes : "<<endl;
		cout<<"\t1. Faire une recherche de chemin en largeur."<<endl;
		cout<<"\t2. Faire une recherche avec l'algorithme de Dijkstra."<<endl;
		cout<<"\t3. Faire une recherche avec l'algorithme de Bellman Ford."<<endl;
		cout<<"\t4. Faire une recherche avec l'algorithme A*."<<endl;
		cout<<"\t5. Visionner la fermeture transitive du graphe." << endl;
		cout<<"\t6. Visionner les tests pré-établis."<<endl;
		cout<<"\t7. Sauvegarder le réseau chargé."<<endl;
		cout<<"\t8. Quitter le programme."<<endl;
		cout<<"\tVeuillez entrer votre choix : ";

		int choix = 0;
		cin >> choix;
		cin.ignore();
		cout<<endl;
		cout << "---------------------\n" << endl;

		try
		{
			switch (choix)
			{
			case 1:
			{
				cout<<"Algorithme:  Recherche en largeur"<<endl;
				//test algo recherche largeur
				string origine, destination;
				preparerVilles(origine, destination);
				//imprimer le chemin & temps d'execution
				clock_t temps;
				temps = clock();
				vector<string> chemin = reseau.rechercheCheminLargeur(origine, destination);
				temps = clock()-temps;
				cout<<"Temps d'exécution : "<<(float)temps/CLOCKS_PER_SEC<<" secondes"<<endl;
				if (chemin.size()==0)
					cout << "Il n'y a aucun trajet possible entre les deux villes."<<endl;
				else
				{
					cout<<"Trajet : "<<endl;
					for (size_t i = 0; i < chemin.size() ; i++)
					{
						cout<<"\t"<<chemin[i]<<endl;
					}
				}
				cout << "---------------------\n" << endl;
			}
			break;
			case 2:
			{
				cout<<"Algorithme:  Dijkstra"<<endl;
				//test algo dijkstra
				string origine, destination;
				preparerVilles(origine,destination);
				cout<<"Vous pouvez chercher le plus court chemin selon une des options suivantes : "<<endl;
				cout<<"\t1. La durée du parcours en temps."<<endl;
				cout<<"\t2. Le coût du trajet."<<endl;
				cout<<"\tVeuillez entrer votre choix : ";
				int choix = 0;
				cin >> choix;
				cin.ignore();
				choix--;
				cout<<endl;
				clock_t temps;
				temps = clock();
				Chemin reponse = reseau.rechercheCheminDijkstra(origine, destination, choix);
				temps = clock()-temps;
				afficherChemin(reponse, temps);
				cout << "---------------------\n" << endl;
			}
			break;
			case 3:
			{
				cout<<"Algorithme:  Bellman-Ford"<<endl;
				//test algo bellman ford
				string origine, destination;
				preparerVilles(origine, destination);
				cout<<"Vous pouvez chercher le plus court chemin selon une des options suivantes : "<<endl;
				cout<<"\t1. La durée du parcours en temps."<<endl;
				cout<<"\t2. Le coût du trajet."<<endl;
				cout<<"\t3. Le niveau de sécurité total du trajet."<<endl;
				cout<<"\tVeuillez entrer votre choix : ";
				int choix = 0;
				cin >> choix;
				cin.ignore();
				cout<<endl;
				clock_t temps;
				temps = clock();
				Chemin reponse = reseau.bellManFord(origine, destination, choix);
				temps = clock()-temps;
				afficherChemin(reponse, temps);
				cout << "---------------------\n" << endl;
			}
			break;
			case 4:
			{
				cout<<"Algorithme:  A*"<<endl;
				//test algo a*
				string origine, destination;
				preparerVilles(origine, destination);
				cout<<"Vous pouvez chercher le plus court chemin selon une des options suivantes : "<<endl;
				cout<<"\t1. La durée du parcours en temps."<<endl;
				cout<<"\t2. Le coût du trajet."<<endl;
				int choix = 0;
				cin >> choix;
				cin.ignore();
				cout<<endl;
				choix--;
				clock_t temps;
				temps = clock();
				Chemin reponse = reseau.algorithmeAstar(origine, destination, choix);
				temps = clock()-temps;
				afficherChemin(reponse, temps);
				cout << "---------------------\n" << endl;
			}
			break;
			case 5:
			{
				ReseauAerien reseauFerme = reseau.fermetureReseau();
				cout << reseauFerme << endl;
			}
			break;
			case 6:
			{
				ifstream f;
				ReseauAerien resTest;
				string nomFichier2="ReseauAerien.txt";
				f.open(nomFichier2.c_str(), ios::in);
				resTest.chargerReseau(f);


				//largeur
				//1. chemin trouvable
				cout<<"Recherche chemin en largeur : "<<originePossible<<" à "<<destinationPossible<<endl;
				clock_t temps;
				temps = clock();
				vector<string> chemin =resTest.rechercheCheminLargeur(originePossible, destinationPossible);
				temps = clock()-temps;
				cout<<"Temps d'exécution : "<<(float)temps/CLOCKS_PER_SEC*1000<<" millisecondes"<<endl;
				if (chemin.size()==0)
					cout << "Il n'y a aucun trajet possible entre les deux villes."<<endl;
				else
				{
					cout<<"Trajet : "<<endl;
					for (size_t i = 0; i < chemin.size() ; i++)
					{
						cout<<"\t"<<chemin[i]<<endl;
					}
				}
				cout << "---------------------\n" << endl;

				//dijkstra
				//1.  durée
				cout<<"Recherche chemin avec l'algorithme de Dijkstra (ponderation: durée) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repD1 = resTest.rechercheCheminDijkstra(originePossible, destinationPossible, true);
				temps = clock()-temps;
				afficherChemin(repD1, temps);
				cout << "---------------------\n" << endl;

				//2.  cout
				cout<<"Recherche chemin avec l'algorithme de Dijkstra (ponderation: cout) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repD2 = resTest.rechercheCheminDijkstra(originePossible, destinationPossible, false);
				temps = clock()-temps;
				afficherChemin(repD2, temps);
				cout << "---------------------\n" << endl;


				//bellman ford
				//1.  durée
				cout<<"Recherche chemin avec l'algorithme de Bellman-Ford (ponderation: durée) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repBF1 = resTest.bellManFord(originePossible, destinationPossible, 1);
				temps = clock()-temps;
				afficherChemin(repBF1, temps);
				cout << "---------------------\n" << endl;

				//2. cout
				cout<<"Recherche chemin avec l'algorithme de Bellman-Ford (ponderation: cout) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repBF2 = resTest.bellManFord(originePossible, destinationPossible, 2);
				temps = clock()-temps;
				afficherChemin(repBF2, temps);
				cout << "---------------------\n" << endl;

				//3. cout
				cout<<"Recherche chemin avec l'algorithme de Bellman-Ford (ponderation: niv. sécurité) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repBF3 = resTest.bellManFord(originePossible, destinationPossible, 3);
				temps = clock()-temps;
				afficherChemin(repBF3, temps);
				cout << "---------------------\n" << endl;


				//a*
				//1.  durée
				cout<<"Recherche chemin avec l'algorithme A* (ponderation: durée) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repA1 = resTest.algorithmeAstar(originePossible, destinationPossible, true);
				temps = clock()-temps;
				afficherChemin(repA1, temps);
				cout << "---------------------\n" << endl;

				//2.  cout
				cout<<"Recherche chemin avec l'algorithme A* (ponderation: cout) : "<<originePossible<<" à "<<destinationPossible<<endl;
				temps = clock();
				Chemin repA2 = resTest.algorithmeAstar(originePossible, destinationPossible, false);
				temps = clock()-temps;
				afficherChemin(repA2, temps);
				cout << "---------------------\n" << endl;

			}
			break;
			case 7:
			{
				try
				{
					cout << "Veuillez saisir le nom du fichier (avec extension) où vous désirez enregistrer le fichier : ";
					string fichierEnregistrement;
					getline(cin, fichierEnregistrement);
					ofstream fe(fichierEnregistrement.c_str(), std::ofstream::out);
					reseau.sauvegarderReseau(fe);
					fe.close();
				}
				catch (logic_error& le)
				{
					cout<<"**ERREUR** Le fichier n'a pas pu être ouvert correctement."<<endl;
				}

			}
			break;
			case 8:
			{
				//quitter
				cout<<"Au revoir."<<endl;
				fichier.close();
				return 0;
			}
			break;
			default:
			{
				cout<<"Choix invalide.  SVP essayez de nouveau."<<endl;
			}
			}//end switch(choix)

		}
		catch (logic_error& le)
		{
			cout<<"**ERREUR**  Une des villes spécifiées ne fait pas partie du réseau."<<endl;
		}
		catch(bad_alloc& ba)
		{
			cout<<"**ERREUR** Mémoire insuffisante."<<endl;
		}


	}

    return 0;
}
